package com.liang.excel.core;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.liang.excel.core.domain.ResponseData;
import com.liang.excel.core.domain.StoreResponseData;
import lombok.Data;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liangyehao
 * @version 1.0
 * @date 2021/4/26 23:13
 * @content
 */
public class TotalUtils {
    
    public static <T extends ResponseData> void total(List<T> list, T specificSumData) {
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        try {
            ResponseData sumResponseData = sumAll(list);
            rateAll(sumResponseData);
            BeanUtil.copyProperties(sumResponseData,specificSumData);
            list.add(specificSumData);
        } catch (IllegalAccessException e) {
            System.out.println("计算总计异常...");
            e.printStackTrace();
        }
    }

    private static void rateAll(ResponseData responseData) throws IllegalAccessException {
        Field[] fields = responseData.getClass().getDeclaredFields();

        List<RateDTO> rateDTOList = new ArrayList<>();

        for (Field field : fields) {
            field.setAccessible(true);
            ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
            if (excelProperty!=null && excelProperty.value().length==2) {
                RateDTO rateDTO = new RateDTO();
                rateDTO.setField(field);
                rateDTO.setFirstLevel(excelProperty.value()[0]);
                rateDTO.setSecondLevel(excelProperty.value()[1]);
                rateDTOList.add(rateDTO);
            }
        }
        Map<String, List<RateDTO>> collect = rateDTOList.stream().collect(Collectors.groupingBy(RateDTO::getFirstLevel));

        for (Map.Entry<String, List<RateDTO>> entry : collect.entrySet()) {
            List<RateDTO> rateDtoList = entry.getValue();
            RateDTO session = rateDtoList.stream().filter(data -> Constants.SESSION_AMOUNT.equals(data.getSecondLevel())).findFirst().get();
            RateDTO input = rateDtoList.stream().filter(data -> Constants.INPUT_AMOUNT.equals(data.getSecondLevel())).findFirst().get();
            RateDTO inputRt = rateDtoList.stream().filter(data -> Constants.INPUT_RATE.equals(data.getSecondLevel())).findFirst().get();
            RateDTO takeLook = rateDtoList.stream().filter(data -> Constants.TAKE_LOOK_AT_AMOUNT.equals(data.getSecondLevel())).findFirst().get();
            RateDTO takeLookRt = rateDtoList.stream().filter(data -> Constants.TAKE_LOOK_AT_RATE.equals(data.getSecondLevel())).findFirst().get();

            Integer sessionAmount = (Integer) session.getField().get(responseData);

            float i = sessionAmount == 0 ? 0 : (Integer)input.getField().get(responseData) / (float)sessionAmount;
            BigDecimal inputRate = BigDecimal.valueOf(i);
            inputRt.getField().set(responseData,inputRate);

            float j = sessionAmount == 0 ? 0 : (Integer) takeLook.getField().get(responseData) / (float) sessionAmount;
            BigDecimal takeLookRate = BigDecimal.valueOf(j);
            takeLookRt.getField().set(responseData,takeLookRate);

        }
    }

    private static <T> ResponseData sumAll(List<T> list) throws IllegalAccessException {
        ResponseData sumData = new ResponseData();
        sumData.setStore("总计");
        Field[] fields = sumData.getClass().getDeclaredFields();
        for (Field field : fields) {
            if ("Integer".equals(field.getType().getSimpleName())||"int".equals(field.getType().getSimpleName())) {
                field.setAccessible(true);
                int sum = list.stream().map(data -> {
                    try {
                        return field.get(data);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                        return 0;
                    }
                }).mapToInt(i -> (int) i).sum();
                field.set(sumData,sum);
            }
        }
        return sumData;
    }

    @Data
    static
    class RateDTO {
        private String firstLevel;
        private String secondLevel;
        private Field field;
    }


    public static void main(String[] args) throws Exception {
        testTotal();
    }

    private static void testTotal() {
        StoreResponseData responseData = new StoreResponseData();
        responseData.setSessionAmount(50);
        responseData.setInputAmount(13);
        responseData.setTakeLookAtAmount(1);
        StoreResponseData responseData2 = new StoreResponseData();
        responseData2.setSessionAmount(50);
        responseData2.setInputAmount(7);
        responseData2.setTakeLookAtAmount(9);
        List<StoreResponseData> list = new ArrayList<>(Arrays.asList(responseData, responseData2));
        total(list, new StoreResponseData());
        System.out.println();
    }

}
